package com.telit.firecommand.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.xiaolyuh.annotation.Cacheable;
import com.github.xiaolyuh.annotation.FirstCache;
import com.github.xiaolyuh.annotation.SecondaryCache;
import com.telit.firecommand.dao.GeoPkFdiRdDao;
import com.telit.firecommand.dto.GeoPkFdiRdAreaDto;
import com.telit.firecommand.dto.GeoPkFdiRdHotPortAreaNewDto;
import com.telit.firecommand.dto.GeoPkFdiRdResponsibilityZoneDto;
import com.telit.firecommand.entity.GeoPkFdiRd;
import com.telit.firecommand.service.IGeoPkFdiRdService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class GeoPkFdiRdServiceImpl extends ServiceImpl<GeoPkFdiRdDao, GeoPkFdiRd> implements IGeoPkFdiRdService {

    @Override
    @Cacheable(value = "third:pkfdird:statisticAreaByDJ", depict = "根据等级分组统计面积",
            firstCache = @FirstCache(expireTime = 8, timeUnit = TimeUnit.HOURS),
            secondaryCache = @SecondaryCache(expireTime = 12, preloadTime = 2, forceRefresh = true, timeUnit = TimeUnit.HOURS))
    public List<GeoPkFdiRdAreaDto> statisticAreaByDJ(Integer flag, Integer dayFlag, String date,String districtCode) {
        String dateFormatStr = formatDateStrToStr(date);
        //获取当前用户的行政区划
        return baseMapper.statisticAreaByDJ(flag,dayFlag,dateFormatStr,districtCode);
    }

    @Override
    @Cacheable(value = "firecommand:fdird:statisticAreaByHotPortAndDJ",depict = "根据热点和等级统计面积")
    public List<GeoPkFdiRdHotPortAreaNewDto> statisticAreaByHotPortAndDJ(Integer level, Integer dayFlag, String date , String countryName,String districtCode ) throws InterruptedException {

        String dateFormatStr = formatDateStrToStr(date);
        //获取当前用户的区级或者街道级行政区划代码
     //   String villageDistrictCode = JwtTokenUtils.getVillageDistrictCode();
        return baseMapper.statisticAreaContainCunByHotPortAndDJ(level,dayFlag,dateFormatStr,countryName,districtCode);

       /* 以上代码是咨询gis开发工程师后，对应rdid没有重复的情况提供的解决方案，以下代码为原先任务rdid下会存在多个村进行的多线程选择，存在调用次数过多的情况
       String dateFormatStr = formatDateStrToStr(date);
        //获取当前用户的区级或者街道级行政区划代码
        String villageDistrictCode = JwtTokenUtils.getVillageDistrictCode();
        List<GeoPkFdiRdHotPortAreaDto> geoPkFdiRdHotPortAreaDtoList=baseMapper.statisticAreaByHotPortAndDJ(level,dayFlag,dateFormatStr,countryName,villageDistrictCode);

        //分组临界值设定
        int count=50;
        //线程数
        int threadSize=(geoPkFdiRdHotPortAreaDtoList.size()/count)+1;
        ThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(threadSize);
        CountDownLatch countDownLatch=new CountDownLatch(threadSize);
        List<GeoPkFdiRdHotPortAreaDto> newGeoPkFdiRdHotPortAreaDtoList=null;
        List<GeoPkFdiRdHotPortAreaDto> resultGeoPkFdiRdHotPortAreaDtoList=new ArrayList<>();
        for(int i=0;i<threadSize;i++){
            if((i+1)==threadSize){
                int startIndex=i*count;
                int endIndex=geoPkFdiRdHotPortAreaDtoList.size();
                newGeoPkFdiRdHotPortAreaDtoList=geoPkFdiRdHotPortAreaDtoList.subList(startIndex,endIndex);
            }else{
                int startIndex=i*count;
                int endIndex=(i+1)*count;
                newGeoPkFdiRdHotPortAreaDtoList=geoPkFdiRdHotPortAreaDtoList.subList(startIndex,endIndex);
            }
            List<GeoPkFdiRdHotPortAreaDto> subGeoPkFdiRdHotPortAreaDtoList = newGeoPkFdiRdHotPortAreaDtoList;
            executor.execute(()->{
                for(GeoPkFdiRdHotPortAreaDto geoPkFdiRdHotPortAreaDto:subGeoPkFdiRdHotPortAreaDtoList){
                    //修改前
//                    List<CountryDto> countryDtoList=baseMapper.selectCountryByYJID(geoPkFdiRdHotPortAreaDto.getRdid(),dayFlag);
                    //修改后，加数据权限行政区划
                    List<CountryDto> countryDtoList=baseMapper.selectCountryByYJID(geoPkFdiRdHotPortAreaDto.getRdid(),dayFlag,villageDistrictCode);
                    if(countryDtoList!=null && countryDtoList.size()>0) {
                        geoPkFdiRdHotPortAreaDto.setCountryDtoList(countryDtoList);
                        //添加村数量
                        geoPkFdiRdHotPortAreaDto.setCountryCount(countryDtoList.size());
                    }
                }
                resultGeoPkFdiRdHotPortAreaDtoList.addAll(subGeoPkFdiRdHotPortAreaDtoList);
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        System.out.println(resultGeoPkFdiRdHotPortAreaDtoList.size());
        executor.shutdown();
        List<GeoPkFdiRdHotPortAreaDto> geoPkFdiRdHotPortAreaDtoSortList = resultGeoPkFdiRdHotPortAreaDtoList.stream().sorted(Comparator.comparing(GeoPkFdiRdHotPortAreaDto::getMj).reversed()).collect(Collectors.toList());
        return geoPkFdiRdHotPortAreaDtoSortList;*/
    }

    @Override
    @Cacheable(value = "firecommand:fdird:statisticAreaByResponsibilityZone",depict = "根据热点和等级统计面积")
    public List<GeoPkFdiRdResponsibilityZoneDto> statisticAreaByResponsibilityZone(Integer level, Integer dayFlag, String date, String countryName, String districtCode) throws InterruptedException {
        String dateFormatStr = formatDateStrToStr(date);
        //获取当前用户的区级或者街道级行政区划代码
//        String villageDistrictCode = JwtTokenUtils.getVillageDistrictCode();
        List<GeoPkFdiRdResponsibilityZoneDto> geoPkFdiRdResponsibilityZoneDtoList=baseMapper.statisticAreaByResponsibilityZone(level,dayFlag,dateFormatStr,countryName,districtCode);
        //获取指定日期、指定级别下的热点及村数据
        List<Map<String,String>> rdidByDateAndLevelList=baseMapper.selectRdidByDateAndLevel(level,dayFlag,dateFormatStr);
        //把集合中村编码一样的数据进行合并
        Map<String, List<String>> cunMap = rdidByDateAndLevelList.stream().collect(Collectors.toMap(e -> e.get("cun"), e -> new ArrayList<String>(Arrays.asList(e.get("rdid"))), (List<String> oldList, List<String> newList) -> {
            oldList.addAll(newList);
            return oldList;
        }));
        //遍历村对应的热点ID的集合
        geoPkFdiRdResponsibilityZoneDtoList.forEach(
                e->{
                    //从村map中取值，设置rdid集合
                    List<String> rdidByCunList = cunMap.get(e.getCountryCode());
                    if(CollectionUtil.isNotEmpty(rdidByCunList)){
                        e.setYjidList(rdidByCunList);
                        e.setYjidCount(rdidByCunList.size());
                    }
                }
        );
        return geoPkFdiRdResponsibilityZoneDtoList;
        /*String dateFormatStr = formatDateStrToStr(date);
        //获取当前用户的区级或者街道级行政区划代码
        String villageDistrictCode = JwtTokenUtils.getVillageDistrictCode();
        List<GeoPkFdiRdResponsibilityZoneDto> geoPkFdiRdResponsibilityZoneDtoList=baseMapper.statisticAreaByResponsibilityZone(level,dayFlag,dateFormatStr,countryName,villageDistrictCode);
        //分组临界值设定
        int count=50;
        //线程数
        int threadSize=(geoPkFdiRdResponsibilityZoneDtoList.size()/count)+1;
        ThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(threadSize);
        CountDownLatch countDownLatch=new CountDownLatch(threadSize);
        List<GeoPkFdiRdResponsibilityZoneDto> newGeoPkFdiRdHotPortAreaDtoList=null;
        List<GeoPkFdiRdResponsibilityZoneDto> resultGeoPkFdiRdHotPortAreaDtoList=new ArrayList<>();
        for(int i=0;i<threadSize;i++){
            if((i+1)==threadSize){
                int startIndex=i*count;
                int endIndex=geoPkFdiRdResponsibilityZoneDtoList.size();
                newGeoPkFdiRdHotPortAreaDtoList=geoPkFdiRdResponsibilityZoneDtoList.subList(startIndex,endIndex);
            }else{
                int startIndex=i*count;
                int endIndex=(i+1)*count;
                newGeoPkFdiRdHotPortAreaDtoList=geoPkFdiRdResponsibilityZoneDtoList.subList(startIndex,endIndex);
            }
            List<GeoPkFdiRdResponsibilityZoneDto> subGeoPkFdiRdHotPortAreaDtoList = newGeoPkFdiRdHotPortAreaDtoList;
            executor.execute(()->{
                for(GeoPkFdiRdResponsibilityZoneDto geoPkFdiRdResponsibilityZoneDto:subGeoPkFdiRdHotPortAreaDtoList){
                    List<String> yjidList=baseMapper.selectYJIDList(dayFlag,dateFormatStr,level,geoPkFdiRdResponsibilityZoneDto.getCountryCode());
                    if(yjidList!=null && yjidList.size()>0) {
                        geoPkFdiRdResponsibilityZoneDto.setYjidList(yjidList);
                        geoPkFdiRdResponsibilityZoneDto.setYjidCount(yjidList.size());
                    }
                }
                resultGeoPkFdiRdHotPortAreaDtoList.addAll(subGeoPkFdiRdHotPortAreaDtoList);
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        System.out.println(resultGeoPkFdiRdHotPortAreaDtoList.size());
        executor.shutdown();
        List<GeoPkFdiRdResponsibilityZoneDto> geoPkFdiRdResponsibilityZoneDtoSortList = resultGeoPkFdiRdHotPortAreaDtoList.stream().sorted(Comparator.comparing(GeoPkFdiRdResponsibilityZoneDto::getMj).reversed()).collect(Collectors.toList());
        return geoPkFdiRdResponsibilityZoneDtoSortList;*/
    }

    @Override
    public List<GeoPkFdiRdAreaDto> selectMjByYjidAndCun(Integer dayFlag,String cunCode,String yjid,String date,String districtCode) {
        List<String> list = Arrays.asList(yjid.split(","));
        return baseMapper.selectMjByYjidAndCun(dayFlag,cunCode,list,date);
    }

    /**
     * 日期yyyy-MM-dd到yyyyMMdd
     * @param date
     * @return
     */
    private String formatDateStrToStr(String date){
        return DateUtil.format(DateUtil.parse(date), "yyyyMMdd");
    }
}
